using System;
using System.Collections.Generic;
using UnityEngine;

namespace UI.BankingPanel.Data
{
    /// <summary>
    /// 数据模型工厂类，用于创建各种类型的响应式数据模型
    /// 对应Lua版本的DataModel功能
    /// </summary>
    public static class DataModel
    {
        /// <summary>
        /// 创建布尔值模型
        /// </summary>
        public static BooleanModel CreateBoolean(bool initValue = false)
        {
            return new BooleanModel(initValue);
        }

        /// <summary>
        /// 创建值模型
        /// </summary>
        public static ValueModel<T> CreateValue<T>(T initValue = default(T))
        {
            return new ValueModel<T>(initValue);
        }

        /// <summary>
        /// 创建数组模型
        /// </summary>
        public static ArrayModel<T> CreateArray<T>(List<T> initArray = null)
        {
            return new ArrayModel<T>(initArray);
        }

        /// <summary>
        /// 创建字典模型
        /// </summary>
        public static MapModel<TKey, TValue> CreateMap<TKey, TValue>(Dictionary<TKey, TValue> initMap = null)
        {
            return new MapModel<TKey, TValue>(initMap);
        }
    }

    /// <summary>
    /// 观察者ID，用于取消监听
    /// </summary>
    public class WatcherId
    {
        private readonly Action cancelAction;

        public WatcherId(Action cancelAction)
        {
            this.cancelAction = cancelAction;
        }

        public void Cancel()
        {
            cancelAction?.Invoke();
        }
    }

    /// <summary>
    /// 布尔值模型
    /// </summary>
    public class BooleanModel
    {
        private bool value;
        private readonly Dictionary<Action<bool, bool>, bool> watchers = new Dictionary<Action<bool, bool>, bool>();

        public BooleanModel(bool initValue = false)
        {
            this.value = initValue;
        }

        public void Set(bool v)
        {
            bool isChange = this.value != v;
            this.value = v;
            Notify(this.value, isChange);
        }

        public bool Get()
        {
            return value;
        }

        /// <summary>
        /// 添加观察者
        /// </summary>
        /// <param name="watcher">监听回调函数</param>
        /// <param name="immediateRefresh">是否立即回调刷新</param>
        public WatcherId AddWatcher(Action<bool, bool> watcher, bool immediateRefresh = false)
        {
            if (watcher != null)
            {
                watchers[watcher] = true;
                if (immediateRefresh)
                {
                    watcher(value, true);
                }
            }

            return new WatcherId(() => RemoveWatcher(watcher));
        }

        public void RemoveWatcher(Action<bool, bool> watcher)
        {
            if (watcher != null)
            {
                watchers.Remove(watcher);
            }
        }

        private void Notify(bool value, bool isChange)
        {
            foreach (var watcher in watchers.Keys)
            {
                try
                {
                    watcher(value, isChange);
                }
                catch (Exception ex)
                {
                    Debug.LogError($"DataModel watcher error: {ex.Message}\n{ex.StackTrace}");
                }
            }
        }

        public void Refresh()
        {
            Notify(value, false);
        }
    }

    /// <summary>
    /// 泛型值模型
    /// </summary>
    public class ValueModel<T>
    {
        private T value;
        private readonly Dictionary<Action<T, bool>, bool> watchers = new Dictionary<Action<T, bool>, bool>();

        public ValueModel(T initValue = default(T))
        {
            this.value = initValue;
        }

        public void Set(T v)
        {
            if (v == null)
            {
                Debug.LogError("ValueModel.Set: value cannot be null");
                return;
            }

            bool isChange = !EqualityComparer<T>.Default.Equals(this.value, v);
            this.value = v;
            Notify(this.value, isChange);
        }

        public T Get()
        {
            return value;
        }

        /// <summary>
        /// 添加观察者
        /// </summary>
        /// <param name="watcher">监听回调函数</param>
        /// <param name="immediateRefresh">是否立即回调刷新</param>
        public WatcherId AddWatcher(Action<T, bool> watcher, bool immediateRefresh = false)
        {
            if (watcher != null)
            {
                watchers[watcher] = true;
                if (immediateRefresh)
                {
                    watcher(value, true);
                }
            }

            return new WatcherId(() => RemoveWatcher(watcher));
        }

        public void RemoveWatcher(Action<T, bool> watcher)
        {
            if (watcher != null)
            {
                watchers.Remove(watcher);
            }
        }

        private void Notify(T value, bool isChange)
        {
            foreach (var watcher in watchers.Keys)
            {
                try
                {
                    watcher(value, isChange);
                }
                catch (Exception ex)
                {
                    Debug.LogError($"DataModel watcher error: {ex.Message}\n{ex.StackTrace}");
                }
            }
        }

        public void Refresh()
        {
            Notify(value, false);
        }
    }

    /// <summary>
    /// 数组模型
    /// </summary>
    public class ArrayModel<T>
    {
        private List<T> array;
        private readonly List<Action<List<T>, int, T>> watchers = new List<Action<List<T>, int, T>>();

        public ArrayModel(List<T> initArray = null)
        {
            array = new List<T>();
            if (initArray != null)
            {
                Set(initArray);
            }
        }

        public int Size()
        {
            return array.Count;
        }

        public List<T> Get()
        {
            return new List<T>(array); // 返回副本以防外部修改
        }

        public void Set(List<T> newArray)
        {
            if (newArray == null)
            {
                Debug.LogError("ArrayModel.Set: array cannot be null");
                return;
            }

            array = new List<T>(newArray);
            Notify(array, -1, default(T));
        }

        public T GetAt(int index)
        {
            if (index >= 0 && index < array.Count)
            {
                return array[index];
            }
            return default(T);
        }

        public void SetAt(int index, T value)
        {
            if (index >= 0 && index < array.Count)
            {
                array[index] = value;
                Notify(array, index, value);
            }
        }

        public void Append(T value)
        {
            array.Add(value);
            Notify(array, array.Count - 1, value);
        }

        public void SetAll(T value, int? count = null)
        {
            int targetCount = count ?? array.Count;
            for (int i = 0; i < targetCount; i++)
            {
                if (i < array.Count)
                {
                    array[i] = value;
                }
                else
                {
                    array.Add(value);
                }
            }
            Notify(array, -1, default(T));
        }

        public WatcherId AddWatcher(Action<List<T>, int, T> watcher)
        {
            if (watcher != null)
            {
                watchers.Add(watcher);
            }

            return new WatcherId(() => RemoveWatcher(watcher));
        }

        public void RemoveWatcher(Action<List<T>, int, T> watcher)
        {
            if (watcher != null)
            {
                watchers.Remove(watcher);
            }
        }

        private void Notify(List<T> array, int index, T value)
        {
            foreach (var watcher in watchers)
            {
                try
                {
                    watcher(array, index, value);
                }
                catch (Exception ex)
                {
                    Debug.LogError($"DataModel watcher error: {ex.Message}\n{ex.StackTrace}");
                }
            }
        }

        public void CopyFrom(ArrayModel<T> model)
        {
            var sourceArray = model.Get();
            array.Clear();
            array.AddRange(sourceArray);
            Notify(array, -1, default(T));
        }

        public void SetEach(Func<int, T, T> computer)
        {
            for (int i = 0; i < array.Count; i++)
            {
                array[i] = computer(i, array[i]);
            }
            Notify(array, -1, default(T));
        }

        public void ForEach(Action<int, T> handler)
        {
            for (int i = 0; i < array.Count; i++)
            {
                handler(i, array[i]);
            }
        }

        public bool EqualRawArray(List<T> otherArray)
        {
            if (array.Count != otherArray.Count)
            {
                return false;
            }

            for (int i = 0; i < array.Count; i++)
            {
                if (!EqualityComparer<T>.Default.Equals(array[i], otherArray[i]))
                {
                    return false;
                }
            }

            return true;
        }

        public void Refresh()
        {
            Notify(array, -1, default(T));
        }
    }

    /// <summary>
    /// 字典模型
    /// </summary>
    public class MapModel<TKey, TValue>
    {
        private Dictionary<TKey, TValue> map;
        private readonly List<Action<Dictionary<TKey, TValue>, TKey, TValue>> watchers = new List<Action<Dictionary<TKey, TValue>, TKey, TValue>>();

        public MapModel(Dictionary<TKey, TValue> initMap = null)
        {
            map = new Dictionary<TKey, TValue>();
            if (initMap != null)
            {
                Set(initMap);
            }
        }

        public Dictionary<TKey, TValue> Get()
        {
            return new Dictionary<TKey, TValue>(map); // 返回副本以防外部修改
        }

        public void Set(Dictionary<TKey, TValue> newMap)
        {
            if (newMap == null)
            {
                Debug.LogError("MapModel.Set: map cannot be null");
                return;
            }

            map = new Dictionary<TKey, TValue>(newMap);
            Notify(map, default(TKey), default(TValue));
        }

        public TValue GetFor(TKey key)
        {
            return map.TryGetValue(key, out TValue value) ? value : default(TValue);
        }

        public void SetFor(TKey key, TValue value)
        {
            map[key] = value;
            Notify(map, key, value);
        }

        public WatcherId AddWatcher(Action<Dictionary<TKey, TValue>, TKey, TValue> watcher)
        {
            if (watcher != null)
            {
                watchers.Add(watcher);
            }

            return new WatcherId(() => RemoveWatcher(watcher));
        }

        public void RemoveWatcher(Action<Dictionary<TKey, TValue>, TKey, TValue> watcher)
        {
            if (watcher != null)
            {
                watchers.Remove(watcher);
            }
        }

        private void Notify(Dictionary<TKey, TValue> map, TKey key, TValue value)
        {
            foreach (var watcher in watchers)
            {
                try
                {
                    watcher(map, key, value);
                }
                catch (Exception ex)
                {
                    Debug.LogError($"DataModel watcher error: {ex.Message}\n{ex.StackTrace}");
                }
            }
        }

        public void Refresh()
        {
            Notify(map, default(TKey), default(TValue));
        }
    }
} 